﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace Superbaby.PrettyUI.Forms
{
    /// <summary>
    /// Platform Invocation Methods
    /// </summary>
    class NativeMethods
    {
        public struct RECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        #region Windows CE Methods

        [DllImport("coredll", EntryPoint = "RoundRect")]
        private static extern bool RoundRectCE(IntPtr hdc, int nLeftRect, int nTopRect,
            int nRightRect, int nBottomRect, int nWidth, int nHeight);

        [DllImport("coredll", EntryPoint = "CreatePen")]
        private static extern IntPtr CreatePenCE(int penStyle, int width, int crColor);
        public static int PS_SOLID = 0;
        public static int PS_DASH = 1;
        public static int PS_NULL = 5;

        [DllImport("coredll", EntryPoint = "CreateSolidBrush")]
        private static extern IntPtr CreateSolidBrushCE(int crColor);

        [DllImport("coredll", EntryPoint = "SelectObject")]
        private static extern IntPtr SelectObjectCE(IntPtr hdc, IntPtr hgdiobj);

        [DllImport("coredll", EntryPoint = "DeleteObject")]
        private static extern bool DeleteObjectCE(IntPtr hObject);

        [DllImport("coredll", EntryPoint = "GetStockObject")]
        private static extern IntPtr GetStockObjectCE(int fnObject);

        [DllImport("coredll.dll", EntryPoint = "DrawText")]
        private static extern int DrawTextCE(IntPtr hdc, string lpStr, int nCount, ref RECT lpRect, int wFormat);
        public static int DT_CALCRECT = 0x00000400;
        public static int DT_WORDBREAK = 0x00000010;
        public static int DT_NOPREFIX = 0x00000800;
        public static int DT_LEFT = 0x00000000;
        public static int DT_EDITCONTROL = 0x00002000;

        #endregion

        #region Windows Methods

        [DllImport("gdi32", EntryPoint = "RoundRect")]
        private static extern bool RoundRectWin(IntPtr hdc, int nLeftRect, int nTopRect,
            int nRightRect, int nBottomRect, int nWidth, int nHeight);

        [DllImport("gdi32", EntryPoint = "CreatePen")]
        private static extern IntPtr CreatePenWin(int penStyle, int width, int crColor);

        [DllImport("gdi32", EntryPoint = "CreateSolidBrush")]
        private static extern IntPtr CreateSolidBrushWin(int crColor);

        [DllImport("gdi32", EntryPoint = "SelectObject")]
        private static extern IntPtr SelectObjectWin(IntPtr hdc, IntPtr hgdiobj);

        [DllImport("gdi32", EntryPoint = "DeleteObject")]
        private static extern bool DeleteObjectWin(IntPtr hObject);

        [DllImport("gdi32", EntryPoint = "GetStockObject")]
        private static extern IntPtr GetStockObjectWin(int fnObject);

        [DllImport("user32", EntryPoint = "DrawText")]
        private static extern int DrawTextWin(IntPtr hdc, string lpStr, int nCount, ref RECT lpRect, int wFormat);

        #endregion

        #region Platform Agnostic Methods

        /// <summary>
        /// This function draws a rectangle with rounded corners. The current pen outlines the 
        /// rectangle and the current brush fills it.
        /// </summary>
        /// <param name="hdc">Handle to the device context.</param>
        /// <param name="nLeftRect">Specifies the x-coordinate of the upper left corner of 
        /// the rectangle.</param>
        /// <param name="nTopRect">Specifies the y-coordinate of the upper left corner of 
        /// the rectangle.</param>
        /// <param name="nRightRect">Specifies the x-coordinate of the lower right corner 
        /// of the rectangle.</param>
        /// <param name="nBottomRect">Specifies the y-coordinate of the lower right corner
        /// of the rectangle.</param>
        /// <param name="nWidth">Specifies the width of the ellipse used to draw the 
        /// rounded corners.</param>
        /// <param name="nHeight">Specifies the height of the ellipese used to draw the 
        /// rounded corners.</param>
        /// <returns>
        /// Nonzero indicates success. Zero indicates failure. To get extended 
        /// error information, call GetLastError.
        /// </returns>
        internal static bool RoundRect(IntPtr hdc, int nLeftRect, int nTopRect,
     int nRightRect, int nBottomRect, int nWidth, int nHeight)
        {
            bool result = false;
            if (Environment.OSVersion.Platform == PlatformID.WinCE)
            {
                result = RoundRectCE(hdc, nLeftRect, nTopRect, nRightRect,
                    nBottomRect, nWidth, nHeight);
            }
            else
            {
                result = RoundRectWin(hdc, nLeftRect, nTopRect, nRightRect,
                    nBottomRect, nWidth, nHeight);
            }
            return result;
        }

        internal static IntPtr CreatePen(int penStyle, int width, int color)
        {
            IntPtr result = IntPtr.Zero;
            if (Environment.OSVersion.Platform == PlatformID.WinCE)
            {
                result = CreatePenCE(penStyle, width, color);
            }
            else
            {
                result = CreatePenWin(penStyle, width, color);
            }

            return result;
        }

        /// <summary>
        /// This function creates a logical brush that has the specified solid color.
        /// </summary>
        /// <param name="crColor">Specifies the color of the brush.</param>
        /// <returns>
        /// A handle that identifies a logical brush indicates success. NULL 
        /// indicates failure. To get extended error information, call GetLastError.
        /// </returns>
        internal static IntPtr CreateSolidBrush(int crColor)
        {
            IntPtr result = IntPtr.Zero;
            if (Environment.OSVersion.Platform == PlatformID.WinCE)
            {
                result = CreateSolidBrushCE(crColor);
            }
            else
            {
                result = CreateSolidBrushWin(crColor);
            }
            return result;
        }

        internal static int DrawText(IntPtr hdc, string lpStr, int nCount, ref RECT lpRect, int wFormat)
        {
            int result = 0;
            if (Environment.OSVersion.Platform == PlatformID.WinCE)
            {
                result = DrawTextCE(hdc, lpStr, nCount, ref lpRect, wFormat);
            }
            else
            {
                result = DrawTextWin(hdc, lpStr, nCount, ref lpRect, wFormat);
            }
            return result;
        }

        /// <summary>
        /// This function selects an object into a specified device context. The new object 
        /// replaces the previous object of the same type.
        /// </summary>
        /// <param name="hdc">Handle to the device context.</param>
        /// <param name="hgdiobj">Handle to the object to be selected.</param>
        /// <returns>
        /// If the selected object is not a region, the handle of the object being 
        /// replaced indicates success.
        /// </returns>
        internal static IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj)
        {
            IntPtr result = IntPtr.Zero;
            if (Environment.OSVersion.Platform == PlatformID.WinCE)
            {
                result = SelectObjectCE(hdc, hgdiobj);
            }
            else
            {
                result = SelectObjectWin(hdc, hgdiobj);
            }
            return result;
        }

        /// <summary>
        /// This function deletes a logical pen, brush, font, bitmap, region, or palette, 
        /// freeing all system resources associated with the object. After the object is 
        /// deleted, the specified handle is no longer valid.
        /// </summary>
        /// <param name="hObject">Handle to a logical pen, brush, font, bitmap, region, 
        /// or palette.</param>
        /// <returns>Nonzero indicates success.</returns>
        internal static bool DeleteObject(IntPtr hObject)
        {
            bool result = false;
            if (Environment.OSVersion.Platform == PlatformID.WinCE)
            {
                result = DeleteObjectCE(hObject);
            }
            else
            {
                result = DeleteObjectWin(hObject);
            }
            return result;
        }

        /// <summary>
        /// This function retrieves a handle to one of the predefined stock pens, 
        /// brushes or fonts.
        /// </summary>
        /// <param name="fnObject">Specifies the type of stock object.</param>
        /// <returns>If the function succeeds, the return value identifies the 
        /// logical object requested.</returns>
        internal static IntPtr GetStockObject(int fnObject)
        {
            IntPtr result = IntPtr.Zero;
            if (Environment.OSVersion.Platform == PlatformID.WinCE)
            {
                result = GetStockObjectCE(fnObject);
            }
            else
            {
                result = GetStockObjectWin(fnObject);
            }
            return result;
        }

        #endregion
    }

}
